#include "KmyICanvas.h"

KmyICanvas::KmyICanvas()
{
    draw_task_head = NULL;
    draw_task_head_bak = NULL;
    is_need_repaint = true;
    is_drawing = false;
}

KmyICanvas::~KmyICanvas(){
    swapTaskLiskBuff();
    clearDrawTask();
}

DrawTask *KmyICanvas::addDrawTaskImageF(KmyITexture *img,
                                        int dx, int dy, int z,
                                        float alpha, float angle, int flip){
    DrawTask *dt = new DrawTask(img,
                                0, 0, img->width, img->height,
                                dx, dy, img->width, img->height,
                                z,
                                alpha, angle, flip);
    addDrawTask(dt);
    return dt;
}

DrawTask* KmyICanvas::addDrawTaskImageF2(KmyITexture *img,
                                         int sx, int sy, int sw, int sh,
                                         int dx, int dy, int dw, int dh, int z,
                                         float alpha, float angle, int flip){
    DrawTask *dt = new DrawTask(img,
                                sx, sy, sw, sh,
                                dx, dy, dw, dh, z,
                                alpha, angle, flip);
    addDrawTask(dt);
    return dt;
}

DrawTask *KmyICanvas::addDrawTaskImageS(KmyImagePak *imgpak, int img_id,
                                       int dx, int dy,
                                       int z,
                                       float alpha, float angle, int flip){
    St_Rect *range = &(imgpak->ranges[img_id]);
    DrawTask *dt = new DrawTask(imgpak->image,
                                range->x, range->y, range->w, range->h,
                                dx, dy, range->w, range->h,
                                z,
                                alpha, angle, flip);
    addDrawTask(dt);
    return dt;
}

DrawTask *KmyICanvas::addDrawTaskImage(KmyImagePak *imgpak, int img_id,
                                       int dx, int dy, int dw, int dh,
                                       int z,
                                       float alpha, float angle, int flip){
    St_Rect *range = &(imgpak->ranges[img_id]);
    if (dw ==-1){
        dw = range->w;
    }
    if (dh==-1){
        dh = range->h;
    }
    DrawTask *dt = new DrawTask(imgpak->image,
                                range->x, range->y, range->w, range->h,
                                dx, dy, dw, dh,
                                z,
                                alpha, angle, flip);
    addDrawTask(dt);
    return dt;
}

DrawTask *KmyICanvas::addDrawTaskRegion(KmyImagePak *imgpak, int img_id,
                         int sx, int sy, int sw, int sh,
                         int dx, int dy, int dw, int dh,
                                        int z,
                         float alpha, float angle, int flip){
    St_Rect *range = &(imgpak->ranges[img_id]);
    if (sw==-1){
        sw = range->w;
    }
    if (sh == -1){
        sh = range->h;
    }
    if (dw == -1){
        dw = range->w;
    }
    if (dh == -1){
        dh = range->h;
    }
    DrawTask *dt = new DrawTask(imgpak->image,
                                range->x+sx, range->y+sy, sw, sh,
                                dx, dy, dw, dh, z,
                                alpha, angle, flip);
    addDrawTask(dt);
    return dt;
}

DrawTask *KmyICanvas::addDrawTaskMultiImage(KmyITexture *img,
                                            int num, St_Rect *srects, St_Rect2 *drects,
                                            int z, float alpha, float angle){
    DrawTask *dt = new DrawTask(img, num, srects, drects,
                                z, alpha, angle);
    addDrawTask(dt);
    return dt;
}

DrawTask* KmyICanvas::addDrawTaskDupliImage(KmyITexture *img,
                                            St_Rect *srect, int dnum, St_Rect2 *drects,
                                            int z, float alpha, float angle){
    DrawTask *dt = new DrawTask(img, srect, dnum, drects,
                                z, alpha, angle);
    addDrawTask(dt);
    return dt;
}

/** z越大，优先级越小 */
void KmyICanvas::addDrawTask(DrawTask *dt){
    if (dt == NULL){
        return;
    }
    DrawTaskChainNode* dtcn=new DrawTaskChainNode(dt);

    if (draw_task_head_bak==NULL){
        draw_task_head_bak = dtcn;
    }else{
        if (dtcn->dt->z > draw_task_head_bak->dt->z){
            dtcn->next = draw_task_head_bak;
            draw_task_head_bak->pre = dtcn;
            draw_task_head_bak = dtcn;
        }else{
            DrawTaskChainNode *p = draw_task_head_bak->next;
            DrawTaskChainNode *p2 = draw_task_head_bak;
            while (p!=NULL && p->dt->z>=dtcn->dt->z){
                p2 = p;
                p = p->next;
            }
            if (p == NULL){
                dtcn->pre = p2;
                p2->next = dtcn;
            }else{
                p->pre = dtcn;
                dtcn->next = p;
                dtcn->pre = p2;
                p2->next = dtcn;
            }
            return;
        }
    }
}

//void KmyICanvas::removeDrawTask(DrawTask *dt){
//    if (dt->pre == NULL){
//        if (dt == draw_task_head_bak){
//            draw_task_head_bak = dt->next;
//            dt->next = NULL;
//            return;
//        }else{
//            return;
//        }
//    }else if (dt->next == NULL){
//        dt->pre->next = NULL;
//        dt->pre = NULL;
//        return;
//    }else{
//        dt->pre->next = dt->next;
//        dt->next->pre = dt->pre;
//        dt->pre = NULL;
//        dt->next = NULL;
//    }
//}

void KmyICanvas::clearDrawTask(){
    while(is_drawing);

    DrawTaskChainNode *p = draw_task_head;
    DrawTaskChainNode *p0;
    while(p!=NULL && p->next != NULL){
        p0=p;
        p=p->next;
        delete p0;
    }
    if (p==NULL){
        return;
    }
    delete p;
    draw_task_head = NULL;
}

//void KmyICanvas::bindTexturePlus(KmyITexture *tex){
//    if (tex->gid==-1){
//        GLuint id;
//        glGenTextures(1, &id);
//        glBindTexture(GL_TEXTURE_2D, id);
//        switch(tex->mode){
//        case KmyITexture::TEXTURE_MODE_RGBA8:
//            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
//                         tex->width, tex->height, 0, GL_RGBA,  GL_UNSIGNED_BYTE, tex->data);
//            break;
//        case KmyITexture::TEXTURE_MODE_RGBA4:
//            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
//                         tex->width, tex->height, 0, GL_RGBA,  GL_UNSIGNED_SHORT_4_4_4_4, tex->data);
//            break;
//        case KmyITexture::TEXTURE_MODE_ARGB8:
//            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
//                         tex->width, tex->height, 0, GL_RGBA,  GL_UNSIGNED_BYTE, tex->data);
//            break;
//        case KmyITexture::TEXTURE_MODE_ARGB4:
//            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
//                         tex->width, tex->height, 0, GL_RGBA,  GL_UNSIGNED_SHORT_4_4_4_4, tex->data);
//            break;
//        case KmyITexture::TEXTURE_MODE_RGB8:
////            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
////                         tex->width, tex->height, 0, GL_RGB,  GL_UNSIGNED_INTHSORT_4_4_4_4, tex->data);
//            break;
//        case KmyITexture::TEXTURE_MODE_RGB565:
//            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
//                         tex->width, tex->height, 0, GL_RGB,  GL_UNSIGNED_SHORT_5_6_5, tex->data);
//            break;
//        }

//        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
////        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
////                     tex->width, tex->height, 0, GL_RGBA,  0x8365, tex->data);
////        GLuint id = bindTexture(*img, GL_TEXTURE_2D);
////        binded_texture_map.insert(pair<string, GLuint>(name, id));
//        tex->gid = id;
//        tex->is_changed = false;
//    }else if (tex->is_changed){
//        GLuint id = tex->gid;
//        glBindTexture(GL_TEXTURE_2D, id);
//        switch(tex->mode){
//        case KmyITexture::TEXTURE_MODE_RGBA8:
//            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
//                         tex->width, tex->height, 0, GL_RGBA,  GL_UNSIGNED_BYTE, tex->data);
//            break;
//        case KmyITexture::TEXTURE_MODE_RGBA4:
//            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
//                         tex->width, tex->height, 0, GL_RGBA,  GL_UNSIGNED_SHORT_4_4_4_4, tex->data);
//            break;
//        case KmyITexture::TEXTURE_MODE_ARGB8:
//            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
//                         tex->width, tex->height, 0, GL_RGBA,  GL_UNSIGNED_BYTE, tex->data);
//            break;
//        case KmyITexture::TEXTURE_MODE_ARGB4:
//            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,
//                         tex->width, tex->height, 0, GL_RGBA,  GL_UNSIGNED_SHORT_4_4_4_4, tex->data);
//            break;
//        case KmyITexture::TEXTURE_MODE_RGB8:
////            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
////                         tex->width, tex->height, 0, GL_RGB,  GL_UNSIGNED_INTHSORT_4_4_4_4, tex->data);
//            break;
//        case KmyITexture::TEXTURE_MODE_RGB565:
//            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB,
//                         tex->width, tex->height, 0, GL_RGB,  GL_UNSIGNED_SHORT_5_6_5, tex->data);
//            break;
//        }

//        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
//        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
//        tex->is_changed = false;
//    }
//}

//void KmyICanvas::deleteTexturePlus(KmyITexture *tex){
//    deleteTexture(tex->gid);
//    tex->gid = -1;
//}

void KmyICanvas::executeDrawTaskList(){
    swapTaskLiskBuff();
    is_drawing = true;
    DrawTaskChainNode *p = draw_task_head;
    while(p!=NULL){
//        switch (p->draw_type){
//        case DrawTask::DRAW_TYPE_IMAGE_FULL:
//            // 废弃
//            break;
//        case DrawTask::DRAW_TYPE_IMAGE_REGION:
//            drawRegion(p->kmyimage,
//                           p->sx, p->sy, p->sw, p->sh,
//                           p->dx, p->dy, p->dw, p->dh,
//                           p->z,
//                           p->alpha, p->flip, p->angle);
//            break;
//        case DrawTask::DRAW_TYPE_GEOMETRY_LINE:
//            break;
//        case DrawTask::DRAW_TYPE_GEOMETRY_POLYGON:
//            break;
//        case DrawTask::DRAW_TYPE_GEOMETRY_FILL:
//            break;
//        }
        runDrawTask(p->dt);
        p = p->next;
    }
    is_drawing = false;
    is_need_repaint = false;
}

void KmyICanvas::swapTaskLiskBuff(){
    clearDrawTask();
    draw_task_head = draw_task_head_bak;
    draw_task_head_bak = NULL;
}

//void KmyICanvas::update(){
//    if (world!=NULL){
//        world->logic();
//        world->render(this);
//    }
//}
